package checkicon

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"regexp"
	"strings"
	"time"
)

type node struct {
	Id    string `json:"id"`
	Title string `json:"title"`
	Url   string `json:"url"`
	Urls  []node `json:"urls"`
	Icon  string `json:"icon"`
}

// func main() {
// urlstr := "https://kimi.moonshot.cn/chat/cti0abk06opd09aj2vk0"
// urlstr := "https://mirrors.huaweicloud.com/home"

// iconLink, err := getIconLink(urlstr)
// if err != nil {
// 	fmt.Println(err)
// 	return
// }
// fmt.Println(iconLink)
// readbooks()
// }

// contains 函数检查切片中是否包含特定的元素
func contains(slice []int, value int) bool {
	for _, item := range slice {
		if item == value {
			return true
		}
	}
	return false
}

// getIconLink 从指定的URL中获取网站的图标链接
func getIconLink(urlstr string) (string, error) {

	errCode := []int{404, 500, 502, 503, 504}

	// 解析URL字符串为URL对象
	baseUrl, err := url.Parse(urlstr)
	if err != nil {
		return "", err
	}

	// 尝试获取默认的图标链接
	urldef, err := getDefalutIconLink(baseUrl)
	if err == nil {
		return urldef, nil
	}

	// 创建一个HTTP客户端，配置TLS版本
	client := &http.Client{
		Timeout: 10 * time.Second,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				MinVersion: tls.VersionTLS10,
			},
		},
	}
	// 发送GET请求到指定的URL
	res, err := client.Get(urlstr)
	//判断 res.StatusCode 是否在 errCode 中

	if err != nil || contains(errCode, res.StatusCode) {
		return "", fmt.Errorf("not found")
	}

	// 确保请求结束后关闭响应体
	defer res.Body.Close()

	// 创建一个缓冲区来读取响应体
	buf := make([]byte, 1024*1024)
	// 读取响应体内容到缓冲区
	n, err := res.Body.Read(buf)
	if err != nil && err.Error() != "EOF" {
		return "", fmt.Errorf("not found")
	}
	// 初始化图标链接为空字符串
	hrefstr := ""
	// 将读取到的字节转换为字符串
	htmlContent := string(buf[:n])
	// 使用正则表达式查找所有的<link>标签
	linkRegexp := regexp.MustCompile(`<link[^>]*>`)
	// 查找所有匹配的<link>标签
	links := linkRegexp.FindAllString(htmlContent, -1)
	finded := false
	// 遍历所有的<link>标签
	for _, link := range links {
		// 检查链接中是否包含"icon"
		relstr := ""
		relstr, hrefstr = spitLinkFlag(link)
		iconStart := strings.Index(relstr, "icon")
		if iconStart >= 0 {
			finded = true
			break
		}
	}
	// 如果找到了图标链接
	if finded && hrefstr != "" {
		//看是否以是 http开头
		if strings.HasPrefix(hrefstr, "http") {
			return hrefstr, nil
		}
		// 解析图标链接为URL对象
		reaURL, err := url.Parse(hrefstr)
		if err != nil {
			return "", fmt.Errorf("not found")
		}
		// 将图标链接解析为绝对路径
		finalURL := baseUrl.ResolveReference(reaURL)
		// 返回图标链接的字符串形式
		return finalURL.String(), nil
	}
	// 如果没有找到图标链接，则返回错误
	return "", fmt.Errorf("not found")
}

func getDefalutIconLink(urlobj *url.URL) (string, error) {
	favUrl := urlobj.Scheme + "://" + urlobj.Host + "/favicon.ico"
	// 发起 GET 请求, 提定超时时间为 10秒
	client := &http.Client{
		Timeout: 10 * time.Second,
	}
	// 发起 GET 请求
	res, err := client.Get(favUrl)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	// 检查状态码 及 内容类型为 image/x-icon
	if res.StatusCode >= 500 || (res.StatusCode == 200 && res.ContentLength > 0) {
		return favUrl, nil
	} else {
		return "", fmt.Errorf("not found")
	}
}

func spitLinkFlag(linkstr string) (string, string) {
	reRel := regexp.MustCompile(`rel=['"](.*?)['"]`)
	reHref := regexp.MustCompile(`href\s*=\s*['"]?([^'">]+)['"]?`)
	relstr := ""
	hrefstr := ""

	// 提取rel属性的值
	relMatches := reRel.FindStringSubmatch(linkstr)
	if len(relMatches) > 1 {
		relstr = relMatches[1]
	}

	// 提取href属性的值
	hrefMatches := reHref.FindStringSubmatch(linkstr)
	if len(hrefMatches) > 1 {
		// fmt.Printf("href: %s\n", hrefMatches[1])
		hrefstr = hrefMatches[1]
	}
	return relstr, hrefstr
}

func ReadBooks(bookbytes []byte, filename string) error {
	//读取 books.json 文件
	// bookbytes, err := os.ReadFile("books.json")
	// if err != nil {
	// 	fmt.Println(err)
	// 	return
	// }
	//解析 JSON 数据
	var books []node
	err := json.Unmarshal(bookbytes, &books)
	if err != nil {
		// fmt.Println(err)
		return err
	}
	//遍历节点并打印标题和 URL
	for i := range books {
		checkMarks(&books[i])
	}
	//将修改后的 JSON 数据写回文件
	newJsonData, err := json.MarshalIndent(books, "", "  ")
	if err != nil {
		return err
	} else {
		err := os.WriteFile(filename, newJsonData, 0644)
		if err != nil {
			return err
		}
	}
	return nil
}

func checkMarks(node *node) {
	if node.Urls != nil {
		for i := range node.Urls {
			checkMarks(&node.Urls[i])
		}
	} else {
		//fmt.Println(node.Title, node.Url)
		iconLink, err := getIconLink(node.Url)
		if err != nil {
			node.Icon = "icon.jpg"
		} else {
			node.Icon = iconLink
		}
		// len := len(node.Title)
		// if len > 20 {
		// 	node.Title = node.Title[:20] + "..."
		// }
		fmt.Println(node.Title, node.Icon)
	}

}
